package com.lsa.skienna.challenge.chap5;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;

public class c {

	private static final int roundingMode = BigDecimal.ROUND_HALF_DOWN;
	private static final BigDecimal UPPER_BOUND = create("10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
	private static final BigDecimal SQRT_5 = create("2.2360679774997896964091736687313");
	
	private static final int precision = 25;
	
	private static int size = 500;
	
	private static long[] fibs = new long[size];

	/**
	 * @param args
	 */
	public static void main(String[] args) {
//		BigInteger bnd = new BigInteger("10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000");
//		BigInteger bnd = new BigInteger("10000");
//		BigInteger i = new BigInteger("1");
//		for(;i.compareTo(bnd) <= 0; i = i.add(BigInteger.ONE)){
//		}
//		System.out.println("i am out");
		
//		System.out.println(bd);
//		System.out.println(bd.divide(BigDecimal.ONE.add(BigDecimal.ONE)));
		
		fibs[0] = 0;
		fibs[1] = 1;
		
		for (int i = 2; i < size; i++) {
			fibs[i] = fibs[i - 1] + fibs[i - 2];
			BigDecimal estimeNthFib =  estimeNthFib(i);//estimeNthFib(i); create(""+estimateNthFibD(i))
			if (fibs[i] < 0) break;
			//System.out.println(i + " " + estimeNthFib +" " + fibs[i] + " " +  );
			
			System.out.println(i + " " + create(""+estimeNthFib.subtract(BigDecimal.valueOf(fibs[i])), precision));
		}
	}
	
	static BigDecimal create(String val){
		return create(val, precision);
	}
	
	static BigDecimal create(String val, int prec){
		MathContext mc = new MathContext(prec/*, roundingMode*/);
		return new BigDecimal(val, mc);
	}
	
	static BigDecimal estimeNthFib(int n){
		BigDecimal res = create("1").add(SQRT_5);
		BigDecimal two = create("2");
		res = res.divide(two, precision, roundingMode);
//		BigDecimal init = create(""+res);
		res = res.pow(n);
//		for (int i = 1; i < n; i++) {
//			res = res.multiply(init);
//		}
		//res = res.pow(n);
//		return res.divide(SQRT_5, precision, roundingMode);
		return res.divide(SQRT_5, precision, roundingMode);
	}
	
//	private static BigDecimal fib2(int n) {
//	    MathContext mc = new MathContext(n/2, RoundingMode.HALF_DOWN);
//	    BigDecimal is5 = isqrt(new BigDecimal("5"), mc);
//	    BigDecimal one = BigDecimal.ONE;
//	    BigDecimal half = new BigDecimal(0.5);
//	    BigDecimal phi = half.multiply(one.add(one.divide(is5, mc)));
//	    return phi.pow(n, mc).multiply(is5);
//	 }
	
	
	static double estimateNthFibD(int n){
		return Math.pow((1 + Math.sqrt(5)) * 0.5, n) / Math.sqrt(5);
	}
	
	static long fib(int n){
		return fibs[n];
	}
}
